package com.hhwy.framework.code.generation.util;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.hhwy.framework.code.generation.beans.Annotation;
import com.hhwy.framework.code.generation.beans.Bean;
import com.hhwy.framework.code.generation.db.DBContext;
import com.hhwy.framework.code.generation.writer.CodeWriter;
import com.hhwy.framework.code.generation.beans.MetaData;

/**
 * 代码生成工具类
 * @author zhangbaojian
 * @version 1.0
 * @created 21-7月-2014 9:24:59
 */
public class CodeGenerationUtil {

	public static final Logger log = LoggerFactory.getLogger(CodeGenerationUtil.class);
	private Annotation annotation = new Annotation();
	private Bean bean = new Bean();
	private List<MetaData> metaDataList;
	private String codeGenerationPath;
	
	//后台代码生成模板
    public static  final String BASE_PATH = "";
    public static final String BEAN_SERVICE_TEMPLATE_VM_PATH = BASE_PATH + "vms/beanService.vm";
    public static final String BEAN_SERVICE_IMPL_TEMPLATE_VM_PATH = BASE_PATH + "vms/beanServiceImpl.vm";
    public static final String BEAN_SERVICE_TEST_TEMPLATE_VM_PATH = BASE_PATH + "vms/beanServiceTest.vm";
    public static final String BEAN_CONTROLLER_TEMPLATE_VM_PATH = BASE_PATH + "vms/beanController.vm";
    public static final String BEAN_CONTROLLER_TEST_TEMPLATE_VM_PATH = BASE_PATH + "vms/beanControllerTest.vm";
    public static final String BEAN_DOMAIN_TEMPLATE_VM_PATH = BASE_PATH + "vms/bean.vm";

    //前台代码生成模板
    public static final String UI_LIST_TEMPLATE_VM_PATH = BASE_PATH + "vms/miniui/list.vm";
    public static final String UI_ADD_TEMPLATE_VM_PATH = BASE_PATH + "vms/miniui/add.vm";
    public static final String UI_EDIT_TEMPLATE_VM_PATH = BASE_PATH + "vms/miniui/edit.vm";
    public static final String UI_DETAIL_TEMPLATE_VM_PATH = BASE_PATH + "vms/miniui/detail.vm";
	
	//sqlMap映射文件模板路径
	public static final String BEAN_SQLMAPER_TEMPLATE_VM_PATH = "vms/mappers.vm";

    // SQLMap映射文件生成位置
    public static final String SQLMAPER_PATH =  "/src/main/resources/config/maps/mysql/";

	//前端页面生成位置
    public static final String BEAN_JSPPAGE_PATH = "/src/main/resources/templates/epc/";

	
	/**
	 * 初始化信息
	 * @param packagePath
	 * @param tableName
	 * @param sceneName
	 */
	public void init( String codeGenerationPath, String packagePath, String sceneName, String tableName){
		DBContext db = new DBContext();
		metaDataList = db.getMetaDataList(tableName);
		bean.setName(this.getUpperCaseChar(sceneName));
		bean.setLowerName(this.getLowerCaseChar(sceneName));
		bean.setLowerPackageName(bean.getLowerName().toLowerCase());
		bean.setPackagePath(packagePath);
		annotation.setAuthor(System.getProperties().getProperty("user.name"));
		annotation.setDate(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
		annotation.setVersion(PropertyUtil.getValue("version"));
		this.codeGenerationPath = codeGenerationPath;
	}

	public void createController() throws IOException{
        String filePath = codeGenerationPath + "/src/main/java/" + this.getPackagePath()+ bean.getLowerPackageName()
                + "/controller/";
        createFilePath(filePath);
        String fileName = filePath + bean.getName() + "Controller.java";
        File file = new File(fileName);
        FileWriter fw = new FileWriter(file);
        fw.write(createCode(BEAN_CONTROLLER_TEMPLATE_VM_PATH));
        fw.flush();
        fw.close();
	}
	
	public void createControllerTest() throws IOException{
        String filePath = codeGenerationPath + "/src/test/java/" + this.getPackagePath()+ bean.getLowerPackageName()
                + "/controller/";
        createFilePath(filePath);
        String fileName = filePath + bean.getName() + "ControllerTest.java";
        File file = new File(fileName);
        FileWriter fw = new FileWriter(file);
        fw.write(createCode(BEAN_CONTROLLER_TEST_TEMPLATE_VM_PATH));
        fw.flush();
        fw.close();
	}
	
	public void createService() throws IOException{
        String filePath = codeGenerationPath + "/src/main/java/" + this.getPackagePath()+ bean.getLowerPackageName()
                + "/service/";
        createFilePath(filePath);
        String fileName = filePath + bean.getName() + "Service.java";
        File file = new File(fileName);
        FileWriter fw = new FileWriter(file);
        fw.write(createCode(BEAN_SERVICE_TEMPLATE_VM_PATH));
        fw.flush();
        fw.close();
        
        filePath = filePath + "impl/";
        createFilePath(filePath);
        fileName = filePath + bean.getName() + "ServiceImpl.java";
        file = new File(fileName);
        fw = new FileWriter(file);
        fw.write(createCode(BEAN_SERVICE_IMPL_TEMPLATE_VM_PATH));
        fw.flush();
        fw.close();
	}

	public void createServiceTest() throws IOException{
        String filePath = codeGenerationPath + "/src/test/java/" + this.getPackagePath()+ bean.getLowerPackageName()
                + "/service/";
        createFilePath(filePath);
        String fileName = filePath + bean.getName() + "ServiceTest.java";
        File file = new File(fileName);
        FileWriter fw = new FileWriter(file);
        fw.write(createCode(BEAN_SERVICE_TEST_TEMPLATE_VM_PATH));
        fw.flush();
        fw.close();
        
	}
	
	public void createDomain() throws IOException{
        String filePath = codeGenerationPath + "/src/main/java/" + this.getPackagePath()+ bean.getLowerPackageName()
                + "/domain/";
        createFilePath(filePath);
        String fileName = filePath + bean.getName() + ".java";
        File file = new File(fileName);
        FileWriter fw = new FileWriter(file);
        fw.write(createCode(BEAN_DOMAIN_TEMPLATE_VM_PATH));
        fw.flush();
        fw.close();
	}
	
	public void createMappers() throws IOException {
		 String filePath = codeGenerationPath + SQLMAPER_PATH + bean.getLowerPackageName()+ "/";
		 createFilePath(filePath);
		 String fileName = filePath + bean.getLowerName() + "-mapper.xml";
		 File file = new File(fileName);
		 FileWriter fw = new FileWriter(file);
		 fw.write(createCode(BEAN_SQLMAPER_TEMPLATE_VM_PATH));
		 fw.flush();
		 fw.close();
		
	}

	public void createList() throws IOException{
		System.out.println(this.getPackagePath());
        String filePath = codeGenerationPath + BEAN_JSPPAGE_PATH + bean.getLowerPackageName()
                + "/";
        createFilePath(filePath);
        String fileName = filePath + bean.getLowerPackageName()+ "List.jsp";
        File file = new File(fileName);
        FileWriter fw = new FileWriter(file);
        fw.write(createCode(UI_LIST_TEMPLATE_VM_PATH));
        fw.flush();
        fw.close();
	}
	
	public void createAdd() throws IOException{
        String filePath = codeGenerationPath + BEAN_JSPPAGE_PATH + bean.getLowerPackageName()
                + "/";
        createFilePath(filePath);
        String fileName = filePath + bean.getLowerPackageName()+ "Add.jsp";
        File file = new File(fileName);
        FileWriter fw = new FileWriter(file);
        fw.write(createCode(UI_ADD_TEMPLATE_VM_PATH));
        fw.flush();
        fw.close();
	}
	
	public void createEdit() throws IOException{
        String filePath = codeGenerationPath + BEAN_JSPPAGE_PATH + bean.getLowerPackageName()
                + "/";
        createFilePath(filePath);
        String fileName = filePath + bean.getLowerPackageName()+ "Edit.jsp";
        File file = new File(fileName);
        FileWriter fw = new FileWriter(file);
        fw.write(createCode(UI_EDIT_TEMPLATE_VM_PATH));
        fw.flush();
        fw.close();
	}
	
	public void createDetail() throws IOException{
        String filePath = codeGenerationPath + BEAN_JSPPAGE_PATH + bean.getLowerPackageName()
                + "/";
        createFilePath(filePath);
        String fileName = filePath + bean.getLowerPackageName()+ "Info.jsp";
        File file = new File(fileName);
        FileWriter fw = new FileWriter(file);
        fw.write(createCode(UI_DETAIL_TEMPLATE_VM_PATH));
        fw.flush();
        fw.close();
	}
	
	public String createCode(String fileVMPath){
		Velocity.setProperty("input.encoding", "UTF-8");
		Velocity.setProperty("output.encoding", "UTF-8");
		//设置velocity资源加载方式为class        
		Velocity.setProperty("resource.loader", "class");        
		//设置velocity资源加载方式为classpath时的处理类        
		Velocity.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
		Velocity.init();
		String path = codeGenerationPath + fileVMPath;
		Template template = Velocity.getTemplate(fileVMPath);
		VelocityContext velocityContext = new VelocityContext();
		velocityContext.put("bean", bean);
		velocityContext.put("annotation", annotation);
		velocityContext.put("list", metaDataList);
		CodeWriter codeWriter = new CodeWriter();
		template.merge(velocityContext, codeWriter);
		return codeWriter.toString();
	}

	/**
     * 创建文件
     * @param file
     */
    public void createFilePath(String filePath){
    	File file = new File(filePath);
    	if(file.exists()){
    		log.info("已存在目录："+file.getAbsolutePath());
        }else{
        	file.mkdirs();
            log.info("创建["+file.getAbsolutePath()+"]情况成功！");
        }
    }
    
	/**
     * 把第一个字母变为小写<br>
     * 如：Demo demo
     * @param str
     * @return
     */
    public String getLowerCaseChar(String str){
        return str.substring(0,1).toLowerCase()+str.substring(1);
    }
    
    /**
     * 把第一个字母变为大写<br>
     * 如：demo Demo
     * @param str
     * @return
     */
    public String getUpperCaseChar(String str){
        return str.substring(0,1).toUpperCase()+str.substring(1);
    }
    
    public String getPackagePath(){
        return bean.getPackagePath().replace(".", "/")+"/";
    }

	
}